package com.ruoyi.openapi.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.baomidou.mybatisplus.extension.api.R;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.config.BigDataConfig;
import com.ruoyi.common.core.domain.JSONObjectPro;
import com.ruoyi.common.core.domain.OpenApiResult;
import com.ruoyi.common.core.page.AppPage;
import com.ruoyi.common.enums.YesNoEnum;
import com.ruoyi.common.enums.comlbs.*;
import com.ruoyi.common.exception.BigDataException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.http.BigDataResponse;
import com.ruoyi.common.utils.http.CommonResponse;
import com.ruoyi.common.utils.http.HttpRequest;
import com.ruoyi.openapi.domain.request.*;
import com.ruoyi.openapi.service.OpenApiService;
import com.ruoyi.system.domain.VehicleManagement;
import com.ruoyi.system.domain.vo.common.DeviceGps;
import com.ruoyi.system.domain.vo.equipment.EquipmentInfo;
import com.ruoyi.system.service.CommonService;
import com.ruoyi.system.service.IEquipmentManagementService;
import com.ruoyi.system.service.IVehicleManagementService;
import com.ruoyi.system.utils.ComLbsUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述
 * 作者 ZhangPing
 * 创建时间 2023/10/26 17:51
 */
@Service
public class OpenApiServiceImpl implements OpenApiService {

    @Autowired
    private IVehicleManagementService vehicleManagementService;
    @Autowired
    private BigDataConfig bigDataConfig;
    @Autowired
    private IEquipmentManagementService equipmentManagementService;
    @Autowired
    private CommonService commonService;

    /**
     * 获取车辆详情列表
     * @param param
     * @return
     */
    @Override
    public AppPage<JSONObjectPro> getVehicleDetailList(VehicleDetailListParam param){
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<VehicleManagement> vehicleManagementList = vehicleManagementService.selectList(new VehicleManagement()
                .setCompanyId(param.getCompanyId())
                .setNumberPlate(param.getNumberPlate())
                .setBindStatus(param.getBindStatus()));
        //封装显示字段
        List<JSONObjectPro> resultList = vehicleManagementList.stream().map(x -> {
            JSONObjectPro item = new JSONObjectPro()
                .put("id", x.getId())
                .put("numberPlate", x.getNumberPlate())
                .put("companyId", x.getCompanyId())
                .put("companyName", x.getCompanyName())
                .put("companyShortName", x.getCompanyName())
                .put("parentCompanyName", x.getParentCompanyName())
                .put("parentShortName", x.getParentCompanyName())
                .put("vehicleColor", x.getVehicleColor())
                .put("vehiclePic", x.getVehiclePic())
                .put("vehicleBrand", x.getVehicleBrand())
                .put("vehicleModel", x.getVehicleModel())
                .put("bindStatus", x.getBindStatus() != null && x.getBindStatus() == BindStatusEnum.BINDING.getCode() ? "已绑定" : "未绑定")
                .put("bindDeviceId", x.getDeviceId())
                .put("deviceModel", "")
                .put("equipmentType", EquipmentTypeEnum.VEHICLE.getText())
                .put("date", x.getCreateTime());
            return item;
        }).collect(Collectors.toList());
        return new AppPage<>(new PageInfo<>(resultList));
    }

    /**
     * 分页获取车辆历史轨迹
     * @param param
     * @return
     */
    @Override
    public AppPage<JSONObject> getCarHistoryTrack(CarHistoryTrackParam param){
        JSONObjectPro bigDataParam = new JSONObjectPro()
                .put("dvo", param.getDvo())
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
        BigDataResponse<JSONObject> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/gpsRelationData/queryGpsRelationPage", bigDataParam, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        JSONObject data = response.getData();
        List<JSONObject> dataItems = data.getList("dataItems", JSONObject.class);
        int total = data.getIntValue("totalCount");
        int pageIndex = data.getIntValue("pageIndex");
        return new AppPage<>(total, pageIndex, dataItems.size(), dataItems);
    }

    /**
     * 获取车辆历史轨迹
     * @param param
     * @return
     */
    @Override
    public List<JSONObjectPro> getCarHistoryTrackList(CarHistoryTrackParam param){
        JSONObjectPro bigDataParam = new JSONObjectPro()
                .put("dvo", param.getDvo())
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
        BigDataResponse<List<JSONObject>> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/gpsRelationData/queryGpsRelationList",
                bigDataParam, new TypeReference<List<JSONObject>>(){}.getType());
        if (!response.isSuccess()) throw new BigDataException();
        List<JSONObjectPro> resultList = response.getData().stream().map(i -> {
            DeviceGps deviceGps = ComLbsUtils.bigDataGpsFormat(i);
            JSONObjectPro item = new JSONObjectPro()
                    .put("dvo", deviceGps.getDvo())
                    .put("lat", deviceGps.getLat())
                    .put("lng", deviceGps.getLng())
                    .put("hgt", deviceGps.getHgt())
                    .put("spd", deviceGps.getSpd())
                    .put("gte", deviceGps.getGte())
                    .put("gdt", deviceGps.getGdt())
                    .put("mie", deviceGps.getMie() / 1000)
                    .put("ars", deviceGps.getLocation())
                    .put("dre", deviceGps.getDre())
                    .put("sts", deviceGps.getSts());
            return item;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 获取车辆实时定位
     * @param dvo
     * @return
     */
    @Override
    public JSONObjectPro queryRealtimePosition(String dvo){
        //查询单车定位信息
        BigDataResponse<JSONObject> response = HttpRequest.getBigData(bigDataConfig.getApiUrl() + "/gpsData/queryLastGpsOne", new JSONObjectPro().put("dvo", dvo), JSONObject.class);
        if (!response.isSuccess() || response.getData() == null) throw new BigDataException();
        DeviceGps deviceGps = ComLbsUtils.bigDataGpsFormat(response.getData());
        JSONObjectPro resJson = new JSONObjectPro()
                .put("dvo", deviceGps.getDvo())
                .put("lat", deviceGps.getLat())
                .put("lng", deviceGps.getLng())
                .put("hgt", deviceGps.getHgt())
                .put("spd", deviceGps.getSpd())
                .put("gte", deviceGps.getGte())
                .put("gdt", deviceGps.getGdt())
                .put("mie", deviceGps.getMie() / 1000)
                .put("ars", deviceGps.getLocation())
                .put("dre", deviceGps.getDre())
                .put("sts", deviceGps.getSts());
        return resJson;
    }

    /**
     * 获取空气质量数据
     * @param param
     * @return
     */
    @Override
    public List<JSONObjectPro> getAirDetectionDataList(AirDetectionDataListParam param){
        JSONObjectPro bigDataParam = new JSONObjectPro()
                .put("dvos", param.getDvos())
                .put("endPm25", param.getPm25Max())
                .put("startPm25", param.getPm25Min())
                .put("endPm10", param.getPm10Max())
                .put("startPm10", param.getPm10Min())
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
        //远程接口调用
        BigDataResponse<List<JSONObject>> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/upLink/queryUpLink",
                bigDataParam, new TypeReference<List<JSONObject>>(){}.getType());
        if (!response.isSuccess()) return Collections.emptyList();
        List<JSONObjectPro> resultList = response.getData().stream().map(i -> {
            JSONObjectPro item = new JSONObjectPro()
                    .put("dvo", i.get("dvo"))
                    .put("PM2.5", i.get("pmTwoPointFive"))
                    .put("PM10", i.get("pmTen"))
                    .put("date", i.get("pte"));
            return item;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 实时视频点播
     * @param param
     * @return
     */
    @Override
    public JSONObjectPro getRealtimeVideo(RealtimeVideoParam param){
        String queryParam = String.format("devid=%s&channel=%s&msgoperation=%d&streamtype=%d", param.getDvo(), param.getChannel(), param.getMsgOperation(), param.getStreamType());
        CommonResponse<Object> response = HttpRequest.postJson(bigDataConfig.getVideoApiUrl() + "/video45controller/streamingMediaControl?" + queryParam, null, Object.class);
        JSONObjectPro resJson = new JSONObjectPro().put("videoUrl", "");
        if (response.isSuccess() && param.getMsgOperation() == YesNoEnum.NO.getCode()){
            String realtimeVideoUrl = bigDataConfig.getVideoPlayUrl() + "/live/" + param.getDvo() + "-" + param.getChannel() + ".flv";
            resJson.put("videoUrl", realtimeVideoUrl);
        }
        return resJson;
    }

    /**
     * 获取最新空气质量数据
     * @param dvos
     * @return
     */
    @Override
    public List<JSONObjectPro> getLatestAirDetectionData(String[] dvos){
        BigDataResponse<List<JSONObject>> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/upLink/queryLastUpLink",
                new JSONObjectPro().put("dvos", dvos), new TypeReference<List<JSONObject>>() {}.getType());
        if (!response.isSuccess()) return Collections.emptyList();
        List<JSONObjectPro> resultList = response.getData().stream().map(i -> {
            JSONObjectPro item = new JSONObjectPro()
                    .put("dvo", i.get("dvo"))
                    .put("PM2.5", i.get("pmTwoPointFive"))
                    .put("PM10", i.get("pmTen"))
                    .put("date", i.get("pte"));
            return item;
        }).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 获取车辆在线统计
     * @param param
     * @return
     */
    @Override
    public AppPage<JSONObject> getCarOnlineDetail(CarOnlineDetailParam param){
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("numberPlate", param.getNumberPlate())
                .put("dvo", param.getDvo())
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime())
                .put("pageIndex", param.getPageNum())
                .put("pageSize", param.getPageSize())
                .put("companyId", param.getCompanyId());
        BigDataResponse<JSONObject> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/deviceOnlineDetail/queryDeviceOnlineDetailPage", bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        JSONObject data = response.getData();
        int total = data.getIntValue("totalCount");
        List<JSONObject> dataItems = data.getList("dataItems", JSONObject.class);
        return new AppPage<>(total, param.getPageNum(), param.getPageSize(), dataItems);
    }

    /**
     * 获取车辆里程统计
     * @param param
     * @return
     */
    @Override
    public AppPage<JSONObject> getCarMileageDetail(CarMileageDetailParam param){
        JSONObjectPro bigDataParam = new JSONObjectPro()
                .put("pageIndex", param.getPageNum())
                .put("pageSize", param.getPageSize())
                .put("startTime", param.getStartTime())
                .put("endTime", DateUtils.addDay(param.getEndTime(), 1))
                .put("companyId", param.getCompanyId());
        if (param.getDvo() != null) bigDataParam.put("dvo", param.getDvo());
        if (param.getNumberPlate() != null) bigDataParam.put("numberPlate", param.getNumberPlate());
        //远程调用接口
        BigDataResponse<JSONObject> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/deviceMileage/queryDailyPage", bigDataParam, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        int total = response.getData().getIntValue("totalCount");
        List<JSONObject> dataItems = response.getData().getList("dataItems", JSONObject.class);
        return new AppPage<>(total, param.getPageNum(), param.getPageSize(), dataItems);
    }

    /**
     * 获取地图设备列表
     * @return
     */
    public List<JSONObjectPro> getMapDeviceList(){
        //查询车辆列表
        List<EquipmentInfo> equipmentList = equipmentManagementService.selectList(new EquipmentInfo()
                .setActivateStatus(ActivateStatusEnum.ACTIVATED.getCode()) //已激活设备
                .setNumberPlateNotEmpty(true));//设备名称不为空
        List<String> deviceIdList = equipmentList.stream().map(EquipmentInfo::getDeviceId).collect(Collectors.toList());
        //获取车辆最新状态
        Map<String, DeviceGps> cache = commonService.getDeviceOnlineDataFromCache(deviceIdList);
        List<JSONObjectPro> resultList = equipmentList.stream().map(x -> {
            JSONObjectPro item = new JSONObjectPro()
                .put("numberPlate", x.getNumberPlate())
                .put("deviceNo", x.getDeviceId())
                .put("companyId", x.getCompanyId())
                .put("companyName", x.getCompanyName())
                .put("channelsNum", x.getChannels())
                .put("objIcon", x.getObjIcon())
                .put("objType", x.getObjType());
            DeviceGps device = cache.get(x.getDeviceId());
            if (device == null){
                item.put("lat", 0)
                    .put("lng", 0)
                    .put("gpsDateTime", "")
                    .put("status", VehicleStatusEnum.NOT_LOCATE.getCode())
                    .put("vehicleStatus", VehicleStatusEnum.NOT_LOCATE.getText());
                return item;
            }
            item.put("lat", device.getLat())
                    .put("lng", device.getLng())
                    .put("gpsDateTime", device.getGdt())
                    .put("spd", device.getSpd())
                    .put("dre", device.getDre())
                    .put("acc", "关")
                    .put("kilometer", device.getKilometer())
                    .put("dayKMeter", device.getDayKMeter())
                    .put("location", device.getLocation())
                    .put("satelliteCount", device.getSatelliteCount());
            List<Integer> stsList = device.getSts();
            if (stsList.contains(StsListEnum.Acc.getCode())) {
                item.put("acc", "开");
            }
            VehicleStatusEnum vehicleStatusEnum = ComLbsUtils.getObjectStatus(device, x.getObjType());
            item.put("status", vehicleStatusEnum.getCode())
                .put("vehicleStatus", vehicleStatusEnum.getText());
            return item;
        }).sorted(Comparator.comparing(x -> x.get("status").toString())).collect(Collectors.toList());
        return resultList;
    }

}
